/*
 * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2008.
 *
 * Licensed under the Aduna BSD-style license.
 */
package edu.tju.rdfbase.store.helpers;

import edu.tju.rdfbase.store.Store;
import edu.tju.rdfbase.store.StackableStore;

/**
 * Defines utility methods for working with Stores.
 */
public class StoreUtil {

	/**
	 * Property used to enable/disable store debugging.
	 */
	public static final String DEBUG_PROP = "edu.tju.rdfbase.repository.debug";

	private static boolean debugEnabled;

	static {
		try {
			String value = System.getProperty(DEBUG_PROP);
			debugEnabled = value != null && !value.equals("false");
		}
		catch (SecurityException e) {
			// Thrown when not allowed to read system properties, for example when
			// running in applets
			debugEnabled = false;
		}
	}

	/**
	 * Utility method that checks whether store debugging has been enabled.
	 */
	public static boolean isDebugEnabled() {
		return debugEnabled;
	}

	/**
	 * Searches a stack of Stores from top to bottom for a Store that is an
	 * instance of the suppied class or interface. The first Store that matches
	 * (i.e. the one closest to the top) is returned.
	 * 
	 * @param topStore
	 *        The top of the Store stack.
	 * @param storeClass
	 *        A class or interface.
	 * @return A Store that is an instance of storeClass, or null if no such Store
	 *         was found.
	 */
	@SuppressWarnings("unchecked")
	public static <C extends Store> C findStoreInStack(Store topStore, Class<C> storeClass) {
		if (storeClass == null) {
			return null;
		}

		// Check Stores on the stack one by one, starting with the top-most.
		Store currentStore = topStore;

		while (currentStore != null) {
			// Check current Store
			if (storeClass.isInstance(currentStore)) {
				break;
			}

			// Current Store is not an instance of storeClass, check the
			// rest of the stack
			if (currentStore instanceof StackableStore) {
				currentStore = ((StackableStore)currentStore).getDelegate();
			}
			else {
				// We've reached the bottom of the stack
				currentStore = null;
			}
		}

		return (C)currentStore;
	}
}
